package service.validation;

import org.springframework.validation.Errors;

import service.configuration.IFieldStringConfig;
import entities.Status;

public class StringValidator {
	
	/**
	 * Teste si la valeur respecte le nombre minimun de caractère spécifié dans la configuration.
	 * 
	 * @param value la valeur du champs à tester
	 * @param conf la confgiguration du champs de type chaine de caractère (string)
	 * @return true si la regex est précisé et respecté, false sinon
	 */
	protected boolean exceedLowerLimit(String value, IFieldStringConfig conf) {
		return conf.getMinchar() != null && value.length() < conf.getMinchar();
	}
	
	/**
	 * Teste si la valeur respecte la regex spécifié dans la configuration.
	 * 
	 * @param value la valeur du champs à tester
	 * @param conf la confgiguration du champs de type chaine de caractère (string)
	 * @return true si la regex est précisé et respecté, false sinon
	 */
	protected boolean exceedUpperLimit(String value, IFieldStringConfig conf) {
		return conf.getMaxchar() != null && value.length() > conf.getMaxchar();
	}
	
	/**
	 * Teste si la valeur respecte la regex spécifié dans la configuration.
	 * 
	 * @param value la valeur du champs à tester
	 * @param conf la confgiguration du champs de type chaine de caractère (string)
	 * @return true si la regex est précisé et respecté, false sinon
	 */
	protected boolean mismatchRegex(String value, IFieldStringConfig conf) {
		return conf.getRegex() != null && !value.matches(conf.getRegex());
	}
	
	/**
	 * Teste la validité de la valeur d'un champs de type chaine de caractère (string).
	 * 
	 * @param value la valeur du champs à tester
	 * @param conf la confgiguration du champs de type chaine de caractère (string)
	 * @return le status du champs SoftError ou Valid
	 */
	public Status validate(String value, IFieldStringConfig conf) {
		if (conf == null || value == null) {
			return FieldValidator.statusValid;
		}
		if (exceedLowerLimit(value, conf)
				|| exceedUpperLimit(value, conf) 
				|| mismatchRegex(value, conf)) {
			return FieldValidator.statusError;
		}
		return FieldValidator.statusValid;
	}
	
	/**
	 * Teste la validité de la valeur d'un champs de type chaine de caratère (string),
	 * et lie le champs à un message d'erreur en cas d'erreur.
	 * 
	 * @param name le nom du champs, util pour lier un message d'erreur au champs
	 * @param value la valeur du champs à tester
	 * @param conf la confgiguration du champs de type chaine de caratère (string)
	 * @param errors mapping permettant de lier erreurs et messages
	 * @return le status du champs SoftError ou Valid
	 */
	public Status validate(String name, String value, IFieldStringConfig conf, Errors errors) {
			
		if (conf == null || value == null) {
			return FieldValidator.statusValid;
		}
		
		if (exceedLowerLimit(value, conf)) {
			errors.rejectValue(name, "error.field.tooshort", new Object[] {new Integer(conf.getMinchar())}, "");
			return FieldValidator.statusError;
		}
		
		if (exceedUpperLimit(value, conf)) {
			errors.rejectValue(name, "error.field.toolong", new Object[] {new Integer(conf.getMaxchar())}, "");
			return FieldValidator.statusError;
		}
		
		if (mismatchRegex(value, conf)) {
			errors.rejectValue(name, "error.field.badformat");
			return FieldValidator.statusError;
		}
		
		return FieldValidator.statusValid;
	}
}
